package info.niwota.commons.io;

import info.niwota.commons.Hotweb;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore.Images.ImageColumns;
import android.text.TextUtils;

/**
 * @author qiangli
 * 
 */
public final class Files {

	public static final String CONTENT_TYPES_FILE = "/info/niwota/commons/io/content-types.prp";

	public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";

	public static final String CACHE_DIR = "cache";

	public static final String TEMP_DIR = "temp";

	// to keep our cached media files from being auto added to media store
	public static final String CAMOUFLAGE = ".cmf";

	public static Properties contentTypes = new Properties();
	
	public static DateFormat dtf = new SimpleDateFormat("yyyy-MM-dd.hh:mm:ss");
	
	private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

	static {
		loadContentTypes();
	}

	public static String guessContentType(String name) {
		String type = APPLICATION_OCTET_STREAM;
		final String ext = fileExt(name);
		if (ext == null) {
			return type;
		}
		if (contentTypes != null) {
			type = contentTypes.getProperty(ext, type);
		}
		return type;
	}

	public static String guessContentType(Uri uri) {
		String name = uri.getLastPathSegment();
		return guessContentType(name);
	}

	private static void loadContentTypes() {
		try {
			InputStream is = Files.class
					.getResourceAsStream(CONTENT_TYPES_FILE);
			loadContentTypes(is);
			is.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void loadContentTypes(InputStream is) {
		try {
			contentTypes.load(is);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String fileExt(String name) {
		int idx = name.lastIndexOf(".");
		if (idx > 0) {
			return name.substring(idx + 1).toLowerCase();
		}
		return null;
	}

	public static File getCacheDir(Context ctx) {
		return getSubFolder(ctx, CACHE_DIR);
	}
	
	public static File getTempDir(Context ctx) {
		return getSubFolder(ctx, TEMP_DIR);
	}

	/**
	 * 
	 * @return application root file /sdcard/<pkg>
	 */
	public static File getRoot(Context ctx) {
		File esd = Environment.getExternalStorageDirectory();
		String pkg = getPkgName(ctx);
		File dir = new File(esd, pkg);
		return dir;
	}

	private static File getSubFolder(Context ctx, String sub) {
		File root = getRoot(ctx);
		File dir = new File(root, sub);
		return dir;
	}

	private static String getPkgName(Context ctx) {
		String pkg = Hotweb.getPkgName(ctx);
		return (pkg == null ? "info.niwota.temp" : pkg);
	}
	
	public static File getTempFile(Context ctx, String prefix, String ext)
			throws IOException {
		File dir = getTempDir(ctx);
		if (!dir.mkdirs()) {
			throw new IOException("can't create temp folder " + dir);
		}
		return File.createTempFile(prefix, ext, dir);
	}

	public static String guessImageType(String path, String defval) {
		String ext = fileExt(path);
		if (ext == null) {
			return defval;
		}
		//
		final String[] imageExts = new String[] { "png", "jpg", "gif", "ico" };
		final String[] imageTypes = new String[] { "image/png", "image/jpeg",
				"image/gif", "image/vnd.microsoft.icon" };
		int len = imageExts.length;
		for (int i = 0; i < len; i++) {
			if (imageExts[i].equals(ext)) {
				return imageTypes[i];
			}
		}
		return defval;
	}

	public static String guessVideoType(String path, String defval) {
		String ext = fileExt(path);
		if (ext == null) {
			return defval;
		}
		//
		final String[] videoExts = new String[] { "3gp", "mp4", "wmv" };
		final String[] videoTypes = new String[] { "video/3gpp", "video/mpeg",
				"video/*" };
		int len = videoExts.length;
		for (int i = 0; i < len; i++) {
			if (videoExts[i].equals(ext)) {
				return videoTypes[i];
			}
		}
		return defval;
	}

	/**
	 * Create a cache file and ensure parent exists, append a suffix .cmf so it
	 * won't be added to media store
	 * 
	 * @param ctx
	 * @param pathname
	 * @return
	 */
	public static File camouflage(Context ctx, String pathname) {
		File cache = getCacheDir(ctx);
		File f = new File(cache, pathname + CAMOUFLAGE);
		if (!f.exists()) {
			f.getParentFile().mkdirs();
		}
		return f;
	}

	public static File toFile(String uri) {
		if (uri.startsWith("file:")) {
			Uri u = Uri.parse(uri);
			String p = u.getPath();
			return new File(p);
		}
		return new File(uri);
	}

	public static Uri toUri(String path) {
		if (path.startsWith("file:")) {
			return Uri.parse(path);
		}
		return Uri.parse("file:" + path);
	}

	public static String getDataPath(Context ctx, Uri uri) {
		if (uri != null) {
			Cursor c = ctx.getContentResolver().query(uri,
					new String[] { ImageColumns.DATA }, null, null, null);
			c.moveToFirst();
			String p = c.getString(0);
			c.close();
			return p;
		}
		return null;
	}

	private Files() {
	}


	public static File getSubDir(Context ctx, String sub) {
		File root = Files.getRoot(ctx);
		File dir = new File(root, sub);
		return dir;
	}

	public static String guessContentType(String name, String deftype) {
		final String ext = fileExt(name);
		if (ext == null) {
			return deftype;
		}
		if (contentTypes != null) {
			deftype = contentTypes.getProperty(ext, deftype);
			if (deftype != null) {
				deftype = deftype.trim();
			}
		}
		return deftype;
	}
	
	public static String basename(String name) {
		int idx = name.lastIndexOf(".");
		if (idx > 0) {
			return name.substring(0, idx);
		}
		return name;
	}

	public static String formatSize(long size) {
		StringBuilder sb = new StringBuilder();
		if (size < 0) {
			return ("-");
		}
		if (size < 1024) {
			sb.append(size);
			sb.append("B");
			return sb.toString();
		}
		size /= 1024;
		if (size < 1024) {
			sb.append(size);
			sb.append("KB");
			return sb.toString();
		}
		size /= 1024;
		sb.append(size);
		sb.append("MB");

		return sb.toString();
	}

	public static String formatDate(Date date) {
		return df.format(date);
	}

	public static String formatDateTime(Date date) {
		return dtf.format(date);
	}

	public static String cachePath(Uri u) {
		final String scheme = u.getScheme();
		final String p1 = (TextUtils.isEmpty(scheme) ? "internal" : scheme);
		final String auth = u.getAuthority();
		final String p2 = (TextUtils.isEmpty(auth) ? "" : "/" + auth);
		final String path = u.getPath();
		final String p3 = (TextUtils.isEmpty(path) ? "/file" : (path
				.endsWith("/") ? path + "file" : path));
		final String cp = p1 + p2 + p3;
		return cp;
	}
}
